# 同一行业十家公司不同年份营业收入横向、纵向对比 # 姓名:耿鑫艳 # 学号:0194954 # 将"文化娱乐行业.xlsx"转换为"文化娱乐行业.csv" import pandas as pd import openpyxl import re import os os.chdir(r'C:\Users\HP\Desktop\金融数据获取参考文件\大作业') xlsx = '文化娱乐行业.xlsx' df = pd.read_excel(xlsx)#读取excel表格中的内容 exf = openpyxl.load_workbook(xlsx) sheet = exf.active #选择"活跃"的表格 C2 = sheet['C2'] C = sheet['C'] links = [c.value for c in C] links_1 = links[1:-1] links_2 = ''.join(links_1) p = re.compile('"(.*?)","(.*?)"') list_of_tuple = p.findall(links_2) df2 = pd.DataFrame({'link': [t[0] for t in list_of_tuple], 'f_name': [t[1] for t in list_of_tuple]}) print(df2) df2.to_csv('文化娱乐行业.csv') # 对“文化娱乐行业.csv”中f_name列进行重命名并进行筛选,保留所需要的年报内容 # 对f_name列进行匹配重命名 import re import pandas as pd import os df = pd.read_csv("文化娱乐行业.csv",engine = "python",encoding = "utf-8") p = re.compile("(?<=\d{4})(年度年报)|(年报)|(年年报)") f_names = [p.sub("年年度报告",f) for f in df.f_name] df["f_name"] = f_names;del p,f_names print(df) # 定义"filter_links"函数用于对表格f_name一列进行筛选,保留所需要的年报 def filter_links(words,df,include=True): ls=[] for word in words: if include: ls.append([word in f for f in df.f_name]) else: ls.append([word not in f for f in df.f_name]) index = [] for r in range(len(df)): flag = not include for c in range(len(words)): if include: flag = flag or ls[c][r] else: flag = flag and ls[c][r] index.append(flag) df2 = df[index] return(df2) df_all = filter_links(["摘要","述职报告","社会责任","审计","财务","风险","债券",],df,include= False) #false为剔除的部分 df_orig = filter_links(["(","("],df_all,include = False)#剔除带括号的年报 只保留没括号的年报 df_updt = filter_links(["(","("],df_all,include = True)#带括号的年报 print(df_orig) # 定义"sub_with_update"函数,通过该函数对f_name列进行整理,以公司简称分类 def sub_with_update(df_updt,df_orig): df_newest = df_orig.copy() index_orig=[] index_updt=[] for i,f in enumerate(df_orig.f_name): for j,fn in enumerate(df_updt.f_name): if f in fn: index_orig.append(i) index_updt.append(j) for n in range(len(index_orig)): i = index_orig[n] j = index_updt[n] df_newest.iloc[i,-2] = df_updt.iloc[j,-2] return(df_newest) df_newest = sub_with_update(df_updt,df_orig) df_newest.sort_values(by = ["f_name"],inplace=True,ignore_index=True) df_newest["公司简称"] = [f[:4] for f in df_newest.f_name] print(df_newest) # 根据排列情况,提取年报数量最多的十家公司,并将链接存储于"10companies"文件夹中 counts = df_newest["公司简称"].value_counts() ten_company = [] for cn in counts.index[:10]: ten_company.append(filter_links([cn],df_newest)) if not os.path.exists("10companies"): os.makedirs("10companies") for df_com in ten_company: cn = df_com["公司简称"].iloc[0] df_com.to_csv("10companies/%s.csv" % cn) ten_csv = os.listdir("10companies") # 根据所形成的"10companies"文件夹,对内部的csv文件进行拆分,形成下载pdf年报的链接 import re import os import requests import pandas as pd import time #利用for循环对文件夹中十个csv文件分别处理获取链接 for info in os.listdir('10companies'): domain = os.path.abspath(r'10companies') #获取文件夹的路径 info = os.path.join(domain,info) #将路径与文件名结合起来就是每个文件的完整路径 df = pd.read_csv(info) links = df["link"];f_names = df["f_name"] def get_PDF_url(url): r = requests.get(url); r.encoding = 'utf-8'; html = r.text r.close() # 已获取html内容,结束connection p = re.compile('(.*?)', re.DOTALL) a = p.search(html) # 因第一个即是目标标签,故用search if a is None: Warning('没有找到下载链接。请手动检查链接:%s' % url) return() else: href = a.group(1); fname = a.group(2).strip() href = r.url[:26] + href # 形成完整的链接 return((href,fname)) hrefs = []; fnames = [] for link in links: href,fname = get_PDF_url(link) hrefs.append(href) fnames.append(fname) time.sleep(0) df_final_links = pd.DataFrame({'href': hrefs, 'f_name': fnames}) ste = info[-8:-4]#将各个公司的名称赋予ste变量 df_final_links.to_csv("final_links_"+ste+".csv")#将不同公司的年报链接分别储存在不同的csv文件 #运行选出的公司有一家公司通过代码无法获得年报链接的csv 故手动删除 # 通过提取下载后csv文件里的链接,下载各家公司各个年份的年报pdf文件 import os import requests import pandas as pd import time for info in os.listdir('10companies'):#通过for循环对不同csv文件分别进行处理 domain = os.path.abspath(r'10companies') #获取文件夹的路径 info = os.path.join(domain,info) #将路径与文件名结合起来就是每个文件的完整路径 df = pd.read_csv(info) ste = info[-8:-4] df_final_links = pd.read_csv("final_links_"+ste+".csv") hrefs = df_final_links["href"] f_names = df_final_links["f_name"] for i in range(len(hrefs)):#对每个csv文件中已生成的链接通过for循环进行下载 href = hrefs[i];f_name = f_names[i] r = requests.get(href,allow_redirects=True) open('%s'%f_name,'wb').write(r.content) time.sleep(0) r.close() # 为了后续操作简便,已将下载好的pdf文件放到不同的文件夹,并进行相应命名 # 通过正则匹配定位年报中主要会计数据——当年的营业收入,提取放入DataFrame import fitz # pip install pymupdf import re import pandas as pd import os import matplotlib.pyplot as plt import matplotlib import numpy as np df = pd.DataFrame() i = 0 for info in os.listdir('10companies'): domain = os.path.abspath(r'10companies') #获取文件夹的路径 info = os.path.join(domain,info) ste = info[-8:-4]#将公司名称赋给st3 filenames = os.listdir(ste)#获取各个公司文件夹中pdf文件的名称 sale = [] for pdf in filenames: pdf = "\\"+pdf x = "C:\\Users\\HP\\Desktop\\金融数据获取参考文件\\大作业\\"+ste+pdf #形成路径链接 def getText(pdf):#定义函数获取文本 text = '' doc = fitz.open(pdf) for page in doc: text += page.getText() doc.close() text = text.replace(" "," \n") text = text.replace("\n\n","\n") return(text) def get_content(pdf): text = getText(pdf) p = re.compile('(?<=\\n)\D、\s*\D*?主要\D*?数据\D*?\s*(?=\\n)(.*?)经营活动产生的',re.DOTALL)#定位各个年报固定位置的内容 content = p.search(text).group(0) return(content) def parse_data_line(pdf): content = get_content(pdf) subp = "([0-9,.%\- ]*?)\n" psub = "%s%s%s%s" % (subp,subp,subp,subp) p =re.compile("(?<=\\n)营业(\D*?\n)+%s" % psub)#定义营业收入那一行的内容 lines = p.search(content) lines = lines[0]#形成列表内容 return(lines) sale_gain = parse_data_line(x) sale_gain = sale_gain.split("\n")#将列表里的字符串以换行符进行分割,形成新的列表 sale_gain = sale_gain[1]#取列表中第二个字符串,即营业收入 sale.append(sale_gain)#将营业收入放入新的列表 df.insert(i, ste, sale)#以列为单位加入表格 i=i+1 print(df) df.to_csv("9companies")#将循环后生成的DataFrame表格形成一个新的csv文件 # 通过表格制作营业收入的对比图 # 以行为单位取营业收入为列表,并将列表中的字符串类型转为浮点型 import matplotlib.pyplot as plt import matplotlib import numpy as np import pandas as pd import csv from matplotlib.pyplot import MultipleLocator import numpy as np csv_data1 = pd.read_csv("9companies") csv_df1 = pd.DataFrame(csv_data1) csv_df_new1 = csv_df1.iloc[:7,1:11]#得到包含所有公司不同年份营业收入的表格 list_row = csv_df_new1.values.tolist()#以行为单位取成列表 list_name = list(csv_df_new1)#取行业名称 columns = csv_df_new1.columns list_columns = [] for c in columns: d = csv_df_new1[c].values.tolist() list_columns.append(d)#以列为单位取成列表 for i in range(len(list_row)): print(list_row[i]) print("\n") import matplotlib.pyplot as plt import matplotlib import numpy as np import pandas as pd import csv from matplotlib.pyplot import MultipleLocator import numpy as np csv_data1 = pd.read_csv("9companies") csv_df1 = pd.DataFrame(csv_data1) csv_df_new1 = csv_df1.iloc[:7,1:11]#得到包含所有公司不同年份营业收入的表格 list_row = csv_df_new1.values.tolist()#以行为单位取成列表 list_name = list(csv_df_new1)#取行业名称 columns = csv_df_new1.columns list_columns = [] for c in columns: d = csv_df_new1[c].values.tolist() list_columns.append(d)#以列为单位取成列表 print(list_name) for i in range(len(list_row)): print(list_row[i]) print("\n") # 定义change_type的函数,将营业收入由字符串类型转变为浮点型,并保留两位小数 def change_type(list_x): list_want=[] for i in range(len(list_x)): x_a = [] for j in range(len(list_x[1])): a_a = list_x[i][j] a_b = a_a.replace(",","")#将字符串中的,替换为空格 a_c = float(a_b) a_d = a_c / 10**8#将数值缩小为亿分之一,便于在后续图标上展示 a_e = round(a_d,2)#保留两位小数 x_a.append(a_e) list_want.append(x_a) return(list_want) list_row_1 = change_type(list_row) list_columns_1 = change_type(list_columns) for i in range(len(list_row_1)): print(list_row_1[i]) for i in range(len(list_columns_1)): print(list_columns_1[i]) # 制图: #纵向对比图由于同一个公司一年的营业收入有调整前后两个数值导致绘图较乱 暂未找到有效解决办法 以下为运行代码 但输出图像存在问题 # 制图:定义x_ticks函数,由于制作同一公司(十家)不同年份营业收入的对比即纵向对比(柱状图) zhfont1 = matplotlib.font_manager.FontProperties(fname="C:\\Windows\\\Fonts\\SimHei.TTF") name_list = ["2019","2020"] def x_ticks(list_columns,list_name): num_list = list_columns rects = plt.bar(range(len(list_columns)),num_list,color="rgb",width = 1,tick_label=name_list) plt.title(list_name+"2019——2020营业收入对比",fontproperties = zhfont1) plt.xlabel("年份",fontproperties = zhfont1) plt.ylabel("营业收入(亿元)",fontproperties = zhfont1) for rect in rects: height = rect.get_height() plt.text(rect.get_x() + rect.get_width() / 2, height, str(height), size=10, ha="center", va="bottom") plt.savefig(list_name +".png",dpi = 600) plt.show() for i in range(len(list_columns)): x_ticks(list_columns_1[i], list_name[i]) #横向制图 用于制作不同公司同一年份(2019——2020)营业收入的对比即横向对比(条形图) list_name_1 = [] for i in range(len(list_name)):#保留公司名称的前两个字 c_a = list_name[i] c_b = c_a[0:2] list_name_1.append(c_b) def y_ticks(list_row,name_list): num_list_1 = list_row rects = plt.barh(range(len(list_row)),num_list_1,color='rgby') N = 9 index = np.arange(N) plt.yticks(index,list_name_1,fontproperties = zhfont1) plt.title(name_list+"不同公司营业收入对比",fontproperties = zhfont1) plt.xlabel("营业收入(亿元)",fontproperties = zhfont1) plt.ylabel("公司名称",fontproperties = zhfont1) for rect in rects: w=rect.get_width() plt.text(w,rect.get_y()+rect.get_height()/2,w,size =10,ha='left',va='center') plt.savefig(name_list +".png",dpi = 600) plt.show() for i in range(len(list_row)): y_ticks(list_row_1[i], name_list[i])